package cc.admin.modules.graduate.service.impl;

import cc.admin.modules.graduate.entity.BlankQuestions;
import cc.admin.modules.graduate.entity.MediaFiles;
import cc.admin.modules.graduate.entity.UploadFileParams;
import cc.admin.modules.graduate.entity.uploadFileVo;
import cc.admin.modules.graduate.mapper.BlankQuestionsMapper;
import cc.admin.modules.graduate.mapper.MediaFileMapper;
import cc.admin.modules.graduate.service.IBlankQuestionsService;
import cc.admin.modules.graduate.service.IMediaFileService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import io.minio.MinioClient;
import io.minio.RemoveObjectArgs;
import io.minio.UploadObjectArgs;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
@Service
public class MediaFileServiceImpl  extends ServiceImpl<MediaFileMapper, MediaFiles> implements IMediaFileService {

    @Autowired
    MinioClient minioClient;

    @Autowired
    MediaFileMapper mediaFilesMapper;

    @Autowired
    BlankQuestionsMapper blankQuestionsMapper;


    //获取文件默认存储目录路径 年/月/日
    private String getDefaultFolderPath() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String folder = sdf.format(new Date()).replace("-", "/")+"/";
        return folder;
    }



    private String getMimeType(String extension){
        if(extension==null)
            extension = "";
        //根据扩展名取出mimeType
        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension);
        //通用mimeType，字节流
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
        if(extensionMatch!=null){
            mimeType = extensionMatch.getMimeType();
        }
        return mimeType;
    }

    public boolean addMediaFilesToMinIO(String localFilePath,String mimeType,String bucket, String objectName) {
        try {
            UploadObjectArgs testbucket = UploadObjectArgs.builder()
                    .bucket(bucket)
                    .object(objectName)
                    .filename(localFilePath)
                    .contentType(mimeType)
                    .build();
            minioClient.uploadObject(testbucket);
            log.debug("上传文件到minio成功,bucket:{},objectName:{}",bucket,objectName);
            System.out.println("上传成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上传文件到minio出错,bucket:{},objectName:{},错误原因:{}",bucket,objectName,e.getMessage(),e);
        }
        return false;
    }


    /**
     * @description 将文件信息添加到文件表
     * @param subjectId  专业id
     * @param fileMd5  文件md5值
     * @param uploadFileParams  上传文件的信息
     * @param bucket  桶
     * @param objectName 对象名称
     * @return com.xuecheng.media.model.po.MediaFiles
     */
    @Transactional
    public MediaFiles addMediaFilesToDb(String subjectId, String fileMd5, UploadFileParams uploadFileParams, String bucket, String objectName,String mimeType,String filename){
        //从数据库查询文件
        MediaFiles mediaFiles = mediaFilesMapper.selectById(fileMd5);
        if (mediaFiles == null) {
            mediaFiles = new MediaFiles();
            //拷贝基本信息
            BeanUtils.copyProperties(uploadFileParams, mediaFiles);
            mediaFiles.setId(fileMd5);
            mediaFiles.setUrl("/" + bucket + "/" + objectName);
            mediaFiles.setBucket(bucket);
            mediaFiles.setFileType(mimeType);
            mediaFiles.setFilePath(objectName);
            mediaFiles.setFileName(filename);
            //保存文件信息到文件表
            int insert = mediaFilesMapper.insert(mediaFiles);
            if (insert < 0) {
                log.error("保存文件信息到数据库失败,{}",mediaFiles.toString());

            }
            log.debug("保存文件信息到数据库成功,{}",mediaFiles.toString());

        }
        return mediaFiles;

    }


    @Transactional
    @Override
    public uploadFileVo uploadFile(String subjectId, UploadFileParams uploadFileParams, String localFilePath) {
        File file = new File(localFilePath);
        if (!file.exists()) {
            log.error("文件不存在");
        }
        //文件名称
        String filename = uploadFileParams.getFilename();
        //文件扩展名
        String extension = filename.substring(filename.lastIndexOf("."));
        //文件mimeType
        String mimeType = getMimeType(extension);
        //文件的md5值
        String fileMd5 = getFileMD5(file);
        //文件的默认目录
        String defaultFolderPath = getDefaultFolderPath();
        //存储到minio中的对象名(带目录)
        String  objectName = defaultFolderPath + fileMd5 + extension;
        //将文件上传到minio
        boolean b = addMediaFilesToMinIO(localFilePath, mimeType, "video", objectName);
        //文件大小
        uploadFileParams.setFileSize(file.length());
        //将文件信息存储到数据库  TODO 将专业信息录入
        MediaFiles mediaFiles = addMediaFilesToDb(subjectId, fileMd5, uploadFileParams, "video", objectName,mimeType,filename);
        //准备返回数据
        uploadFileVo uploadFileVo = new uploadFileVo();
        BeanUtils.copyProperties(mediaFiles, uploadFileVo);
        return uploadFileVo;

    }
    public String getFileMD5(File file){
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            String fileMD5 = DigestUtils.md5Hex(fileInputStream);
            return fileMD5;
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.error("获取文件md5失败");
        return null;
    }

    public Boolean deleteVideoToDB(String url){
        try {
            LambdaQueryWrapper<BlankQuestions> blankQuestionsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            blankQuestionsLambdaQueryWrapper.eq(BlankQuestions::getViedoUrl, url);
            BlankQuestions blankQuestion = new BlankQuestions();
            blankQuestion.setViedoUrl("");
            blankQuestionsMapper.update(blankQuestion,blankQuestionsLambdaQueryWrapper);

            return true;
        } catch (Exception e) {
            return false;

        }

    }

    @Override
    @Transactional
    public boolean deleteVideo(String url){
        try {

            Boolean aBoolean = deleteVideoToDB(url);
            if (aBoolean){
                System.out.println("数据库删除视频信息");
            }
            System.out.println("删除成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("删除失败");
        }

        return false;
    }

}
